/***************************************************************************************************
 *Copyright(C),2010-2017,Sumscope
 *FileName	:  DictLoadListener.h
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2017/04/10
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#pragma once

#include <core/time/time.h>

#include "DictTable.h"

namespace qb {
namespace ht {
/*
将字典从字典文件(映射文件fmap)中读取然后更新到内存中的容器中时,需要实现此类
每种字典有一个基本的记录类型,如kDictTypeBondList,其记录类型为BOND_LIST,可参考DictDesc::GetStockDictDesc

OnLoadStart,告知调用方,当前字典文件中有多少条记录需要读取,recordType是记录类型的字符串名称,只用于调试确认

OnLoadRecord中,rid是此记录存储在字典文件中的序号,record是内部读取到的对应该序号的单条记录的内存,size为其大小
其中,size==sizeof(记录类型)
使用时,可直接将record强行转换为记录类型的指针
有多少条记录,OnLoadRecord就会被调用多少遍
每次OnLoadRecord被调用,rid会递增,record指针相同,但内容已由DictManager准备好

如何使用:
针对kDictType的13中,需要实现13个此类的子类,如kDictTypeBondList
class DictLoadListenerForBondList : public DictLoaderListener{
public:
virtual void OnLoadStart(int count, const char* recordType)
{
//对AfxGetBondContainer()进行预备扩容,避免后续OnLoadRecord里面的多次扩容
//扩展
}
virtual void OnLoadRecord(int rid, const char* record, int size)
{
BASSERT(size==sizeof(BOND_LIST) && rid>=0);
const BOND_LIST& bl = *((const BOND_LIST*)record);
AfxGetBondContainer().AddBondInfo(CONVERT(bl));
}
};
*/
typedef qb::base::HighResTime HighResTime;
typedef qb::base::BaseString BaseString;

class RecordEnumerator {  // 整个是临时对象
 public:
  class Iterator {
    int m_index;
    RecordEnumerator* m_owner;

   public:
    Iterator(RecordEnumerator* owner, int index)
        : m_owner(owner), m_index(index) {}
    Iterator(const Iterator& ri) : m_owner(ri.m_owner), m_index(ri.m_index) {}
    Iterator& operator=(const Iterator& ri) {
      m_owner = ri.m_owner;
      m_index = ri.m_index;
      return *this;
    }
    void operator++() { m_index++; }
    bool operator!=(const Iterator& ri) const {
      return m_owner != ri.m_owner || m_index != ri.m_index;
    }
    bool operator==(const Iterator& ri) const {
      return m_owner == ri.m_owner && m_index == ri.m_index;
    }
    const char* GetRecord() { return m_owner->ReadRecord(m_index); }
    int GetRecordLength() const { return m_owner->GetRecordLength(); }
  };

 protected:
  struct RecordIndex {
    DictTable::RecordState state;
    RecordId rid;
  };
  DictTable* m_table;
  int m_count;
  bool m_all;
  std::vector<RecordIndex> m_indexes;
  std::vector<unsigned int> m_records;
  Iterator m_end;

 public:
  RecordEnumerator(DictTable* table, bool all);
  void BindTable(DictTable* table, bool all);
  DictTable* GetTable() { return m_table; }
  int GetRecordLength() const { return m_table->GetRecordLength(); }
  int GetRecordCount() const { return m_table->GetRecordCount(); }
  bool IsAllMode() const { return m_all; }
  bool IsEmpty() const;
  const char* ReadRecord(int index);
  Iterator begin() { return Iterator(this, 0); }
  const Iterator end() const { return m_end; }
};
class DictLoaderListener {
  kDictType m_type;

 public:
  DictLoaderListener(kDictType type) : m_type(type) {}
  virtual ~DictLoaderListener() {}
  virtual void LoadRecords(RecordEnumerator& enumerator, kDictType type);
  void SetLanguage(bool en);
};

}  // namespace ht
}  // namespace qb
